package com.sxpcwlkj.system.service.impl;

import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sxpcwlkj.common.exception.LoginException;
import com.sxpcwlkj.common.utils.*;
import com.sxpcwlkj.framework.config.LoginObject;
import com.sxpcwlkj.framework.entity.page.PageQuery;
import com.sxpcwlkj.framework.entity.page.TableDataInfo;
import com.sxpcwlkj.framework.mapper.DataBaseHelper;
import com.sxpcwlkj.common.code.entity.PrivateKeyEntity;
import com.sxpcwlkj.system.entity.*;
import com.sxpcwlkj.system.entity.bo.SysUserBo;
import com.sxpcwlkj.system.entity.vo.SysDeptVo;
import com.sxpcwlkj.system.entity.vo.SysFunctionVo;
import com.sxpcwlkj.system.entity.vo.SysRoleVo;
import com.sxpcwlkj.system.entity.vo.SysUserVo;
import com.sxpcwlkj.common.enums.SystemCommonEnum;
import com.sxpcwlkj.common.exception.ServiceException;
import com.sxpcwlkj.system.mapper.*;
import com.sxpcwlkj.system.service.SysDeptService;
import com.sxpcwlkj.system.service.SysUserService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.*;

@RequiredArgsConstructor
@Service("sysUser")
@Slf4j
public class SysUserServiceImpl implements SysUserService {

    private final SysUserMapper baseMapper;
    private final SysDeptMapper sysDeptMapper;
    private final SysUserRoleMapper sysUserRoleMapper;
    private final SysRoleMapper sysRoleMapper;
    private final SysRoleFunctionMapper sysUserFunctionMapper;
    private final SysFunctionMapper sysFunctionMapper;
    private final SysDeptService sysDeptService;

    @Override
    public TableDataInfo<SysUserVo> selectPageUserList(SysUserBo bo, PageQuery pageQuery) {
        Page<SysUserVo> page = baseMapper.selectPageUserList(pageQuery.build(), this.buildQueryWrapper(bo));
        for (SysUserVo s : page.getRecords()) {
            List<SysDeptVo> list = new ArrayList<>();
            sysDeptService.queryListSon(s.getDeptId(), list);
            Collections.reverse(list);
            s.setDeptIds(list.stream().map(SysDeptVo::getDeptId).toArray(Long[]::new));
        }
        return TableDataInfo.build(page);
    }

    @Override
    public SysUserVo selectVoById(String userId) {
        SysUserVo userVo = baseMapper.selectVoById(userId);
        if (userVo != null) {
            // 部门
            List<SysDeptVo> list = new ArrayList<>();
            sysDeptService.queryListSon(userVo.getDeptId(), list);
            Collections.reverse(list);
            userVo.setDeptIds(list.stream().map(SysDeptVo::getDeptId).toArray(Long[]::new));
            // 角色
            SysRoleVo sysRoleVo = sysRoleMapper.selectByUserId(userId);
            if (sysRoleVo != null) {
                userVo.setRoleId(sysRoleVo.getId());
                userVo.setRoleCode(sysRoleVo.getCode());
                userVo.setRoleName(sysRoleVo.getName());
            }
            //解密数据库的密码
            if (StringUtil.isEmpty(userVo.getAesKey())) {
                //throw new ServiceException("缺少加密KEY!");
                //生成一个
                String key = EncryptionUtil.getAesKey();
                baseMapper.update(null, new LambdaUpdateWrapper<SysUser>().eq(SysUser::getUserId, userId).set(SysUser::getAesKey, key));
                userVo.setAesKey(key);
            }
            String decryptRsa = EncryptionUtil.decryptAes(userVo.getPassword(), userVo.getAesKey());
            userVo.setPassword(decryptRsa);
        }
        return userVo;
    }

    @Override
    public Boolean updateById(SysUserBo bo) {
        int row = 0;
        if (bo.getPassword().length() < 6) {
            throw new ServiceException("密码至少6位！");
        }
        SysUserVo userVo = baseMapper.selectVoById(bo.getUserId());
        if (StringUtil.isEmpty(userVo.getAesKey())) {
            throw new ServiceException("缺少加密KEY!");
        }
        //加密密码
        String encryptRsa = EncryptionUtil.encryptAes(bo.getPassword(), userVo.getAesKey());
        bo.setPassword(encryptRsa);
        SysUser user = MapstructUtil.convert(bo, SysUser.class);
        row = baseMapper.updateById(user);
        if (row > 0) {
            return Boolean.TRUE;
        }
        throw new ServiceException("操作失败");
    }


    private Wrapper<SysUser> buildQueryWrapper(SysUserBo bo) {
        Map<String, Object> params = bo.getParams();
        QueryWrapper<SysUser> wrapper = Wrappers.query();
        //角色启用
        wrapper.eq("r.status", SystemCommonEnum.SYS_COMMON_STATE_OPEN.getValue())
                // 用户ID
                .eq(ObjectUtil.isNotNull(bo.getUserId()), "u.user_id", bo.getUserId())
                // 账号查询
                .like(ObjectUtil.isNotNull(bo.getUserName()), "u.user_name", bo.getUserName())
                // 账号状态
                .eq(ObjectUtil.isNotNull(bo.getStatus()), "u.status", bo.getStatus())
                // 手机号
                .like(ObjectUtil.isNotNull(bo.getPhonenumber()), "u.phonenumber", bo.getPhonenumber())
                // 创建时间
                .between(params.get("beginTime") != null && params.get("endTime") != null,
                        "u.created_time", params.get("beginTime"), params.get("endTime"))
                .and(ObjectUtil.isNotNull(bo.getDeptId()), w -> {
                    List<SysDept> deptList = sysDeptMapper.selectList(new LambdaQueryWrapper<SysDept>()
                            .select(SysDept::getDeptId)
                            .apply(DataBaseHelper.findInSet(bo.getDeptId(), "ancestors")));
                    List<Long> ids = StreamUtil.toList(deptList, SysDept::getDeptId);
                    ids.add(bo.getDeptId());
                    w.in("u.dept_id", ids);
                });
        return wrapper;
    }

    @Override
    public SysUser selectByUserName(String tenantId, String userName) {

        //return sysUserMapper.selectByUserName(userName);
        return baseMapper.selectOne(new QueryWrapper<SysUser>().eq("user_name", userName).last("LIMIT 1"));
    }

    @Override
    public int updateRsa(String tenantId, String userId) {
        PrivateKeyEntity key = EncryptionUtil.getRsaKey();
        log.info("密码对：'{}','{}','{}','{}'", tenantId, userId, key.getPrivateKey(), key.getPrivateKey());
        return baseMapper.updateRsa(tenantId, userId, key.getPrivateKey(), key.getPrivateKey());
    }

    @Override
    public SysUserVo getUserRoleAnfFunctionInfo(String userId) {
        SysUserVo userVo = null;
        SysUser user = baseMapper.selectById(userId);

        if (user != null) {
            userVo = BeanCopyUtil.convert(user, SysUserVo.class);
            //1.角色
            assert userVo != null;
            List<SysRole> sysRoles = sysUserRoleMapper.roleList(userVo.getUserId());
            List<SysRoleVo> sysRoleVos = BeanCopyUtil.convert(sysRoles, SysRoleVo.class);

            //2.资源
            assert sysRoleVos != null;
            //角色资源
            for (SysRoleVo r : sysRoleVos) {
                userVo.setRoleName(sysRoleVos.get(0).getName());
                List<SysFunction> fList = sysUserFunctionMapper.selectByRoleId(r.getId());
                List<SysFunctionVo> roleFunctionVoList = BeanCopyUtil.convert(fList, SysFunctionVo.class);
                r.setSysFunctionVoList(roleFunctionVoList);
                assert roleFunctionVoList != null;

                List<String> list=new ArrayList<>();
                for (int i = 0; i < roleFunctionVoList.size(); i++) {
                    SysFunctionVo functionVo = roleFunctionVoList.get(i);
                    if(StringUtil.isNotEmpty(functionVo.getPermission())){
                        list.add(functionVo.getPermission());
                    }
                }
                r.setPermissions(list.toArray(String[]::new));
            }
            //用户角色列表
            userVo.setRoleVoList(sysRoleVos);
            userVo.setRoleCodes(sysRoleVos.stream().map(SysRoleVo::getCode).toArray(String[]::new));

            //===================超级管理员拥有所有==========================
            if (userVo.getUserId().toString().equals(SystemCommonEnum.SUPER_ADMIN.getValue().toString())) {
                sysRoles = sysRoleMapper.selectList(new LambdaQueryWrapper<SysRole>().eq(SysRole::getCode, SystemCommonEnum.SYS_COMMON_STATE_OPEN.getValue()).like(SysRole::getCode, SystemCommonEnum.SUPER_ADMIN.getCode()).orderByAsc(SysRole::getSort).last("LIMIT 1"));
                sysRoleVos = BeanCopyUtil.convert(sysRoles, SysRoleVo.class);

                List<SysFunction> functionList = sysFunctionMapper.selectList(new LambdaQueryWrapper<SysFunction>().eq(SysFunction::getStatus, SystemCommonEnum.SYS_COMMON_STATE_OPEN.getValue()).orderByAsc(SysFunction::getSort));
                List<SysFunctionVo> roleFunctionVoList = BeanCopyUtil.convert(functionList, SysFunctionVo.class);
                assert sysRoleVos != null;
                sysRoleVos.get(0).setSysFunctionVoList(roleFunctionVoList);
                assert roleFunctionVoList != null;
                List<String> list=new ArrayList<>();
                for (int i = 0; i < roleFunctionVoList.size(); i++) {
                    SysFunctionVo functionVo = roleFunctionVoList.get(i);
                    if(StringUtil.isNotEmpty(functionVo.getPermission())){
                        list.add(functionVo.getPermission());
                    }
                }
                sysRoleVos.get(0).setPermissions(list.toArray(String[]::new));
                //用户角色列表
                userVo.setRoleVoList(sysRoleVos);

                //角色集
                userVo.setRoleCodes(sysRoleVos.stream().map(SysRoleVo::getCode).toArray(String[]::new));
                //资源集
                userVo.setButCodes(list.toArray(String[]::new));
            }


        }

        return userVo;
    }

    @Override
    public List<AdminMenuTree> getAdminMenuTree(String userId) {

        SysUserVo userVo = this.getUserRoleAnfFunctionInfo(userId);
        // 用户角色
        List<SysRoleVo> roleVoList = userVo.getRoleVoList();
        //所有角色
        List<SysFunctionVo> functionVos = new ArrayList<>();
        for (SysRoleVo role : roleVoList) {
            functionVos.addAll(role.getSysFunctionVoList());
        }

        return getAdminMenuTree(functionVos, 1L);
    }


    /**
     * 资源格式化
     *
     * @param functionVos 资源集合
     * @param funId       上级资源ID
     * @return AdminMenuTree
     */
    private List<AdminMenuTree> getAdminMenuTree(List<SysFunctionVo> functionVos, Long funId) {

        List<AdminMenuTree> endList = new ArrayList<>();
        for (SysFunctionVo f : functionVos) {
            //是否是属于funId
            if (f.getParentId() != null && funId.equals(f.getParentId())) {
                if (f.getType() != 1) continue;
                AdminMenuTree menu = new AdminMenuTree();
                menu.setId(f.getId());
                menu.setPath(f.getPath());
                menu.setName(f.getName());
                menu.setComponent(f.getComponent());
                menu.setRedirect(f.getComponentName());

//                {
//                    // 菜单路径，用于跳转
//                    path: '/home',
//                            // 菜单 name，用于界面 keep-alive 路由缓存。
//                            // 此 name 需要与 component 组件中的 name 值相同（唯一）
//                            name: 'home',
//                        // 组件路径
//                        component: () => import('/@/views/home/index.vue'),
//                        // 附加自定义数据
//                        meta: {
//                    // 菜单标题（国际化写法）
//                    title: 'message.router.home',
//                            // 菜单外链链接
//                            // 开启外链条件，`1、isLink: true 2、链接地址不为空（meta.isLink） 3、isIframe: false`
//                            isLink: '',
//                            // 菜单是否隐藏（菜单不显示在界面，但可以进行跳转）
//                            isHide: false,
//                            // 菜单是否缓存
//                            isKeepAlive: true,
//                            // 菜单是否固定（固定在 tagsView 中，不可进行关闭），右键菜单无 `关闭` 项
//                            isAffix: true,
//                            // 是否内嵌
//                            // 开启条件，`1、isIframe: true 2、链接地址不为空（meta.isLink）`
//                            isIframe: false,
//                            // 当前路由权限标识，取角色管理。控制路由显示、隐藏。超级管理员：admin 普通角色：common
//                            // 之前 auth 取用户（角色下有多个用户）
//                            roles: ['admin', 'common'],
//                    // 菜单图标
//                    icon: 'iconfont icon-shouye',
//                    // 自行再添加
//    ...
//                },
//                }


                Map<String, Object> meta = new HashMap<>();

                meta.put("title", f.getLanguageCode());
                meta.put("isLink", f.getIsLink());
                meta.put("isHide", f.getVisible() == 1);
                meta.put("isKeepAlive", f.getKeepAlive() == 1);
                meta.put("isAffix", f.getAlwaysShow() == 1);
                meta.put("isIframe", f.getIsIframe() == 1);
                if (!StringUtil.isEmpty(f.getPermission())) {
                    meta.put("roles", f.getPermission().split(","));
                }
                meta.put("icon", f.getIcon());
                menu.setMeta(meta);
                List<AdminMenuTree> children = getAdminMenuTree(functionVos, f.getId());
                menu.setChildren(children);
                endList.add(menu);
            }
        }

        return endList;

    }


    @Override
    public Boolean insert(SysUserBo bo) {
        // 角色
        SysRoleVo sysRoleVo = sysRoleMapper.selectByCode(bo.getRoleCode());
        if (sysRoleVo == null) {
            throw new ServiceException("选中角色有误!");
        } else {
            bo.setRoleId(sysRoleVo.getId());
        }
        // 不能是超级管理员
        if ("1".equals(bo.getRoleId())) {
            throw new ServiceException("不能是超级管理员!");
        }
        // 检查账号是否去重
        SysUser sysUserName = baseMapper.selectByUserName(bo.getUserName());
        if (sysUserName != null) {
            throw new ServiceException("账号已存在!");
        }
        // 检查账号是否去重
        SysUser sysUserPhone = baseMapper.selectByUserPhone(bo.getPhonenumber());
        if (sysUserPhone != null) {
            throw new ServiceException("手机号已存在!");
        }
        // 检查账号是否去重
        SysUser sysUserEmail = baseMapper.selectByUserName(bo.getEmail());
        if (sysUserEmail != null) {
            throw new ServiceException("邮箱已存在!");
        }


        SysUser sysUser = MapstructUtil.convert(bo, SysUser.class);
        // 新增用户信息
        int rows = baseMapper.insert(sysUser);

        // 新增用户与角色管理
        SysUserRole sysUserRole = new SysUserRole();
        assert sysUser != null;
        sysUserRole.setUserId(sysUser.getUserId());
        sysUserRole.setRoleId(sysRoleVo.getId());
        rows = rows + sysUserRoleMapper.insert(sysUserRole);
        return rows > 1;
    }

    @Override
    public Boolean deleteById(String id) {
        SysUser sysUser = baseMapper.selectById(id);
        if (sysUser != null) {
            //删除角色
            sysUserRoleMapper.delete(new LambdaQueryWrapper<SysUserRole>().eq(SysUserRole::getUserId, id));
        }
        return baseMapper.deleteById(id) > 0;
    }

    @Override
    public Boolean updateHeaderImgById(String headerImg) {
        return baseMapper.update(new LambdaUpdateWrapper<SysUser>().set(SysUser::getAvatar, headerImg).eq(SysUser::getUserId, LoginObject.getLoginId()))>0;
    }


}
